const xlsx = require('node-xlsx')
const fs = require('fs')
const path = require('path')
// 输入路径名（文件or 目录）
const inputPathName = process.argv[2]
main()
// 入口
function main() {
    // 生成输出目录
    // path.parse('/目录1/目录2/文件.txt'); 返回: { root: '/', dir: '/目录1/目录2', base: '文件.txt', ext: '.txt', name: '文件' }
    console.log("输入路径", inputPathName)
    let parsePath = path.parse(inputPathName);
    console.log("解析路径", parsePath)
    // path.dirname('/目录1/目录2/目录3'); 返回: '/目录1/目录2'
    if ([".xls", ".xlsx"].indexOf(parsePath.ext) != -1) { // 单个文件
        outputRoot = path.join(path.dirname(parsePath.dir), 'output')
    } else if (!parsePath.ext) { //目录
        outputRoot = path.join(path.dirname(inputPathName), 'output')
    } else {
        console.log("不是有效文件")
    }
    console.log("输出目录", outputRoot)
    // 同步生成输出目录output
    let checkOutputDir = fs.existsSync(outputRoot);
    if (!checkOutputDir) {
        fs.mkdirSync(outputRoot)
    }
    // client目录
    clientDir = path.join(outputRoot, 'client')
    var checkClientDir = fs.existsSync(clientDir);
    if (!checkClientDir) {
        fs.mkdirSync(clientDir)
    }
    console.log("client目录", clientDir)
    // server目录 
    serverDir = path.join(outputRoot, 'server')
    var checkServerDir = fs.existsSync(serverDir);
    if (!checkServerDir) {
        fs.mkdirSync(serverDir)
    }
    console.log("server目录", serverDir)
    fileOrDirHandler(parsePath)
}
// 文件或目录处理 parsePath 输入路径名解析
function fileOrDirHandler(parsePath) {
    if ([".xls", ".xlsx"].indexOf(parsePath.ext) != -1) { // 单个文件
        readSingleFile(parsePath)
    } else if (!parsePath.ext) { //目录
        execlToJsonAllFilesPromsie(inputPathName)
    } else {
        console.log("不是有效文件")
    }
}
// 写法1------------
// 读取input目录下的所有文件
function execlToJsonAllFiles(pathName) {
    let allFiles = []
    readSingleDir(pathName, allFiles)
    console.log(allFiles)
}
// 读取单层目录
function readSingleDir(pathName, allFiles) {
    let files = fs.readdirSync(pathName)
    files.forEach((item, idnex) => {
        let child = path.join(pathName, item)
        let data = fs.statSync(child)
        // 子目录
        if (data.isDirectory()) {
            readSingleDir(child, allFiles)
        }
        // 文件
        if (data.isFile()) {
            allFiles.push(item)
        }
    }, this)
}
// 单文件
function readSingleFile(parsePath) {
    let promiseFils = []
    let allFiles = []
    promiseFils.push(makePromise(parsePath.dir, parsePath.base, allFiles))
    Promise.all(promiseFils).then((result) => {
        console.log('目录文件读取完成', allFiles)
    })
}
// 写入二 采用promise
function execlToJsonAllFilesPromsie(pathName) {
    let promiseFils = []
    let allFiles = []
    fs.readdir(pathName, (err, files) => {
        files.forEach((item) => {
            if ([".xls", ".xlsx"].indexOf(path.extname(item)) != -1) {
                promiseFils.push(makePromise(pathName, item, allFiles))
            }
        }, this)
        Promise.all(promiseFils).then((result) => {
            console.log('目录文件读取完成', allFiles)
        })
    })
}
function makePromise(pathName, item, allFiles) {
    return new Promise((resolve, reject) => {
        let child = path.join(pathName, item)
        fs.stat(child, (err, info) => {
            if (err) {
                reject(err);   //失败
            } else {
                // 子目录
                if (info.isDirectory()) {
                    execlToJsonAllFilesPromsie(child)
                    resolve();
                }
                // 文件
                if (info.isFile()) {
                    allFiles.push(item)
                    let basename = path.basename(item);
                    let extname = path.extname(item);
                    fileName = basename.substring(0, basename.indexOf(extname));
                    let execlData = execlHandler(child, fileName)
                    resolve({ fileName, client: execlData.dataClient, server: execlData.dataServer, templeteClient: execlData.templeteClient, templeteServer: execlData.templeteServer });    //成功
                }
            }
        })
    }).then((res) => {
        if (res) {
            // client写入
            if (res.client != '[]') {
                writeFiles(res.client, res.fileName, "json", clientDir)
                writeFiles(res.templeteClient, res.fileName, "ts", clientDir)
            }
            // server写入
            if (res.server != '[]') {
                writeFiles(res.server, res.fileName, "json", serverDir)
                writeFiles(res.templeteServer, res.fileName, "ts", serverDir)
            }
        }
    })
}
// 表格处理
function execlHandler(execlPhth, fileName) {
    var sheets = xlsx.parse(execlPhth)
    //sheets是一个数组，数组中的每一项对应test.xlsx这个文件里的多个表格
    let sheet = sheets[0]
    var newSheetsArrClient = [];
    var newSheetsArrServer = [];
    //sheet是一个json对象，格式为{name:"测试参数",data:[]},我们想要的数据就存储在data里
    sheet["data"].shift() //描述
    let outputType = sheet["data"].shift() //导出类型(前端 后端 双端 不导出)
    let type = sheet["data"].shift()
    const key = sheet["data"].shift()
    const val = sheet["data"]
    let templeteClient = ""
    let templeteServer = ""
    if (!outputType || !outputType.length) {
        console.log(`目录${execlPhth} 【outputType】 字段数据为空 请检查！！！！`)
        return
    }
    if (!type || !type.length) {
        console.log(`目录${execlPhth} 【type】 字段数据为空  请检查！！！！`)
        return
    }
    if (!key || !key.length) {
        console.log(`目录${execlPhth} 【key】字段数据为空  请检查！！！！`)
        return
    }
    if (!val || !val.length) {
        console.log(`目录${execlPhth} 【val】 字段数据为空  请检查！！！！`)
        return
    }
    type.forEach((typeItem, index) => {
        if (outputType[index] == "前端") {
            templeteClient += `        public ${key[index].trim()}: ${typeItem.trim()};\n`
        } else if (outputType[index] == "后端") {
            templeteServer += `        public ${key[index].trim()}: ${typeItem.trim()};\n`
        } else if (outputType[index] == "双端") {
            templeteClient += `        public ${key[index].trim()}: ${typeItem.trim()};\n`
            templeteServer += `        public ${key[index].trim()}: ${typeItem.trim()};\n`
        }
    }, this)
    // [id1 name1 level1]
    // [id2 name2 level2]
    // [id3 name3 level3]
    val.forEach((item) => {
        let objClient = {}
        let objServer = {}
        item.forEach((item2, indexVer) => {
            let type = typeof item[indexVer]
            let data = item2
            let csType = outputType[indexVer]
            if (type == "number") {
                if (csType == "前端") {
                    objClient[key[indexVer]] = Number(data)
                } else if (csType == "后端") {
                    objServer[key[indexVer]] = Number(data)
                } else if (csType == "双端") {
                    objClient[key[indexVer]] = Number(data)
                    objServer[key[indexVer]] = Number(data)
                }
            } else if (type == "string") {
                if (csType == "前端") {
                    objClient[key[indexVer]] = /^\[.*\]$/.test(data) ? JSON.parse(data) : data
                } else if (csType == "后端") {
                    objServer[key[indexVer]] = /^\[.*\]$/.test(data) ? JSON.parse(data) : data
                } else if (csType == "双端") {
                    objClient[key[indexVer]] = /^\[.*\]$/.test(data) ? JSON.parse(data) : data
                    objServer[key[indexVer]] = /^\[.*\]$/.test(data) ? JSON.parse(data) : data
                }
            }
        }, this)
        Object.keys(objClient).length && newSheetsArrClient.push(objClient)
        Object.keys(objServer).length && newSheetsArrServer.push(objServer)
    }, this)
    let dataClient = JSON.stringify(newSheetsArrClient)
    let dataServer = JSON.stringify(newSheetsArrServer)
    return { dataClient, dataServer, templeteClient: createTsClass(templeteClient, fileName), templeteServer: createTsClass(templeteServer, fileName) }
}

// 写入文件
function writeFiles(data, pathName, type, pathDir) {
    return new Promise((resolve, reject) => {
        fs.writeFile(path.join(pathDir, '/', pathName + "." + type), data, function () {
            console.log(`写入${pathDir}/${pathName}.${type}成功`)
            resolve()
        })
    })
}
// 转置矩阵
function transposeMatrix(array) {
    array = array.length && array[0].map(function (col, i) {
        return array.map(function (row) {
            return row[i];
        })
    });
    console.log(array)
}
// 创建TS类
function createTsClass(ts, className) {
    var defFileStr = "\/**\n * 该文件为工具自动生成，请勿自行修改。\n **\/\n";
    var templete = "module Templete {\n    export class {0} {\n{1}    }\n}\n";
    templete = templete.replace("{1}", ts).replace("{0}", className)
    console.log(templete)
    return defFileStr + templete
}
function delDir(path) {
    let files = [];
    if (fs.existsSync(path)) {
        files = fs.readdirSync(path);
        files.forEach((file, index) => {
            let curPath = path.join(path, file)
            if (fs.statSync(curPath).isDirectory()) {
                delDir(curPath); //递归删除文件夹
            } else {
                fs.unlinkSync(curPath); //删除文件
            }
        });
        fs.rmdirSync(path);
    }
}
